package sqs

import (
	"os"
	"strconv"
	"goaws.googlecode.com/hg/aws"
)

type Message struct {
	Queue         *Queue
	Id            string
	ReceiptHandle string
	Body          string
	Attributes    aws.AttributeList
}

func (m *Message) String() string {
	return m.Body
}

func (q *Queue) SendMessage(body string) (messageId string, err os.Error) {
	response := new(sendMessageResponse)
	if err = q.getResponse("SendMessage", map[string]string{"MessageBody": body}, response); err != nil {
		return
	}

	if !aws.CheckMD5Digest(body, response.MD5OfMessageBody) {
		return "", os.NewError("Invalid MD5 checksum")
	}

	return response.MessageId, nil
}

func (q *Queue) ReceiveMultipleMessages(maxCount int, visibilityTimeout int, attributes []string) (messages []*Message, err os.Error) {
	params := make(map[string]string)
	if maxCount != 1 || visibilityTimeout >= 0 || attributes != nil {
		if maxCount != 1 {
			params["MaxNumberOfMessages"] = strconv.Itoa(maxCount)
		}
		if visibilityTimeout >= 0 {
			params["VisibilityTimeout"] = strconv.Itoa(visibilityTimeout)
		}
		if len(attributes) > 0 {
			aws.AddAttributeNamesToParams(params, attributes)
		}
	}

	response := new(receiveMessageResponse)
	if err = q.getResponse("ReceiveMessage", params, response); err != nil {
		return
	}

	messages = make([]*Message, 0, len(response.Messages))
	for i, message := range response.Messages {
		if !aws.CheckMD5Digest(message.Body, message.MD5OfBody) {
			return nil, os.NewError("Invalid MD5 checksum")
		}

		messages = append(messages, &Message{q, message.MessageId, message.ReceiptHandle, message.Body, nil})
		if len(message.Attributes) > 0 {
			messages[i].Attributes = message.Attributes
		}
	}

	return messages, nil
}

func (q *Queue) ReceiveMessage() (message *Message, err os.Error) {
	messages, err := q.ReceiveMultipleMessages(1, -1, nil)
	if err == nil && len(messages) > 0 {
		return messages[0], nil
	}

	return
}

func (m *Message) ChangeVisibilityTimeout(visibilityTimeout int) os.Error {
	params := map[string]string{
		"ReceiptHandle":     m.ReceiptHandle,
		"VisibilityTimeout": strconv.Itoa(visibilityTimeout),
	}
	return m.Queue.getResponse("ChangeMessageVisibility", params, nil)
}

func (m *Message) Delete() os.Error {
	return m.Queue.getResponse("DeleteMessage", map[string]string{"ReceiptHandle": m.ReceiptHandle}, nil)
}
